"""拖放功能组件"""

import tkinter as tk
from tkinter import ttk
from typing import List, Callable, Optional
from pathlib import Path
import platform


class DragDropFrame(ttk.Frame):
    """支持拖放的框架组件"""
    
    def __init__(self, parent, drop_callback: Callable[[List[str]], None], **kwargs):
        """初始化拖放框架
        
        Args:
            parent: 父组件
            drop_callback: 文件拖放回调函数，接收文件路径列表
        """
        super().__init__(parent, **kwargs)
        self.drop_callback = drop_callback
        self._setup_drag_drop()
        self._create_ui()
    
    def _setup_drag_drop(self) -> None:
        """设置拖放功能"""
        # 注册拖放事件
        self.drop_target_register('*')
        
        # 绑定拖放事件
        self.bind('<Button-1>', self._on_click)
        self.bind('<B1-Motion>', self._on_drag)
        self.bind('<ButtonRelease-1>', self._on_drop)
        
        # 跨平台拖放支持
        if platform.system() == "Windows":
            self._setup_windows_drag_drop()
        else:
            self._setup_unix_drag_drop()
    
    def _setup_windows_drag_drop(self) -> None:
        """Windows拖放设置"""
        try:
            # 使用tkinterdnd2库（如果可用）
            from tkinterdnd2 import DND_FILES
            
            self.drop_target_register(DND_FILES)
            self.dnd_bind('<<Drop>>', self._on_file_drop)
            self.dnd_bind('<<DragEnter>>', self._on_drag_enter)
            self.dnd_bind('<<DragLeave>>', self._on_drag_leave)
            
        except ImportError:
            # 如果没有tkinterdnd2，使用基本实现
            self._setup_basic_drag_drop()
    
    def _setup_unix_drag_drop(self) -> None:
        """Unix/Linux拖放设置"""
        # 绑定X11拖放事件
        self.bind('<Button-2>', self._on_middle_click)  # 中键粘贴
        self._setup_basic_drag_drop()
    
    def _setup_basic_drag_drop(self) -> None:
        """基本拖放实现"""
        # 使用剪贴板作为备用方案
        self.bind('<Control-v>', self._on_paste)
        self.focus_set()
    
    def _create_ui(self) -> None:
        """创建UI元素"""
        # 主容器
        self.container = ttk.Frame(self)
        self.container.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 拖放区域
        self.drop_area = tk.Frame(
            self.container,
            bg='#f0f0f0',
            relief=tk.RAISED,
            borderwidth=2
        )
        self.drop_area.pack(fill=tk.BOTH, expand=True)
        
        # 提示标签
        self.label = tk.Label(
            self.drop_area,
            text="将文件拖放到此区域\n或点击选择文件",
            font=('Microsoft YaHei', 12),
            bg='#f0f0f0',
            fg='#666666'
        )
        self.label.pack(expand=True)
        
        # 选择文件按钮
        self.select_button = ttk.Button(
            self.drop_area,
            text="选择文件",
            command=self._select_files
        )
        self.select_button.pack(pady=10)
        
        # 绑定区域事件
        self.drop_area.bind('<Button-1>', lambda e: self._select_files())
        self.label.bind('<Button-1>', lambda e: self._select_files())
        
        # 绑定拖放区域的所有子组件
        self._bind_drop_events(self.drop_area)
    
    def _bind_drop_events(self, widget) -> None:
        """递归绑定拖放事件到所有子组件"""
        try:
            if hasattr(widget, 'dnd_bind'):
                widget.dnd_bind('<<Drop>>', self._on_file_drop)
                widget.dnd_bind('<<DragEnter>>', self._on_drag_enter)
                widget.dnd_bind('<<DragLeave>>', self._on_drag_leave)
        except:
            pass
        
        # 递归处理子组件
        for child in widget.winfo_children():
            self._bind_drop_events(child)
    
    def _on_file_drop(self, event) -> None:
        """文件拖放事件处理"""
        try:
            # 解析拖放的文件列表
            files = self._parse_drop_data(event.data)
            
            # 过滤有效文件
            valid_files = []
            for file_path in files:
                path = Path(file_path)
                if path.exists() and path.is_file():
                    valid_files.append(str(path))
            
            if valid_files:
                self._highlight_drop_area(False)
                self.drop_callback(valid_files)
            
        except Exception as e:
            print(f"拖放处理错误: {e}")
    
    def _parse_drop_data(self, data: str) -> List[str]:
        """解析拖放数据"""
        if not data:
            return []
        
        # 处理多种数据格式
        files = []
        
        # Windows格式: {path1} {path2}
        if data.startswith('{') and '}' in data:
            import re
            files = re.findall(r'\{([^}]+)\}', data)
        
        # Unix格式: file://path1 file://path2
        elif 'file://' in data:
            parts = data.split()
            for part in parts:
                if part.startswith('file://'):
                    file_path = part[7:]  # 移除 file://
                    files.append(file_path)
        
        # 简单空格分隔
        else:
            files = data.split()
        
        return [f.strip(' \'"') for f in files if f.strip()]
    
    def _on_drag_enter(self, event) -> None:
        """拖放进入事件"""
        self._highlight_drop_area(True)
    
    def _on_drag_leave(self, event) -> None:
        """拖放离开事件"""
        self._highlight_drop_area(False)
    
    def _highlight_drop_area(self, highlight: bool) -> None:
        """高亮拖放区域"""
        if highlight:
            self.drop_area.config(bg='#e6f3ff', relief=tk.SOLID, borderwidth=2)
            self.label.config(bg='#e6f3ff', fg='#0066cc')
        else:
            self.drop_area.config(bg='#f0f0f0', relief=tk.RAISED, borderwidth=2)
            self.label.config(bg='#f0f0f0', fg='#666666')
    
    def _select_files(self) -> None:
        """选择文件对话框"""
        from tkinter import filedialog
        
        files = filedialog.askopenfilenames(
            title="选择要归档的文件",
            filetypes=[
                ("所有文件", "*.*"),
                ("文档文件", "*.pdf *.docx *.doc *.txt"),
                ("图片文件", "*.jpg *.jpeg *.png *.gif"),
                ("视频文件", "*.mp4 *.avi *.mkv *.mov")
            ]
        )
        
        if files:
            self.drop_callback(list(files))
    
    def _on_click(self, event) -> None:
        """点击事件"""
        self.focus_set()
    
    def _on_drag(self, event) -> None:
        """拖拽事件"""
        pass
    
    def _on_drop(self, event) -> None:
        """放置事件"""
        pass
    
    def _on_middle_click(self, event) -> None:
        """中键点击事件（Unix系统）"""
        try:
            # 尝试从剪贴板获取文件路径
            clipboard_text = self.clipboard_get()
            if clipboard_text:
                lines = clipboard_text.strip().split('\n')
                files = []
                for line in lines:
                    path = Path(line.strip())
                    if path.exists() and path.is_file():
                        files.append(str(path))
                
                if files:
                    self.drop_callback(files)
        except:
            pass
    
    def _on_paste(self, event) -> None:
        """粘贴事件"""
        self._on_middle_click(event)
    
    def drop_target_register(self, *args) -> None:
        """注册拖放目标（兼容性方法）"""
        # 这是一个兼容性方法，实际实现取决于可用的拖放库
        pass
    
    def dnd_bind(self, sequence: str, func: Callable, add: Optional[str] = None) -> None:
        """绑定拖放事件（兼容性方法）"""
        # 这是一个兼容性方法，实际实现取决于可用的拖放库
        pass
    
    def set_status(self, text: str) -> None:
        """设置状态文本"""
        self.label.config(text=text)
    
    def reset_status(self) -> None:
        """重置状态文本"""
        self.label.config(text="将文件拖放到此区域\n或点击选择文件")